<?php


namespace App\Models\CacheModel\lucky;


use App\Models\CacheModel\UserCoupon;
use App\Models\CacheModel\ZlCouponAttr;
use app\common\lib\exception\ApiException;
use app\common\lib\SensorsData;
use App\Models\Api\BaseCache;
use App\Models\Api\Goods;
use think\Db;
use think\Log;
use AstroTool\Cache\CacheManage;

class AppUserLuckyChangeRecord extends BaseCache
{
    protected $table = 'wechat_backup_07_18_14_43_00.app_user_lucky_change_record';

    protected $cacheModel = 'lucky_planet.change_record';
    protected $signInCacheModel = 'lucky_planet.sign_in';   // 签到 缓存 配置

    public $luckyExpireDay = 30; // 幸运星过期 天数  单位 天

    /**
     * 获取 今日用户签到信息
     * @param int $uid
     * @param string $date 20220507
     * @return array|bool
     * @throws \Exception
     */
    public function getUserSignInfoByToday(int $uid, string $date)
    {
        return CacheManage::getInstance()->setCacheConfig($this->signInCacheModel, $uid . ':' . $date)->getDataAndSet(function () use ($uid, $date)
        {
            try
            {
                $time = strtotime($date);
                $data = $this->where(['uid' => $uid, 'task_id' => ['in', [1, 8]]])->where('create_time', '>=', $time)->where('create_time', '<', $time + 86400)->field('task_id,create_time')->order('create_time asc')->findOrFail()->toArray();
                $resData = [
                    'num' => 0,
                    'time' => 0
                ];

                foreach ($data as $datum)
                {
                    if ($datum['task_id'] == 1)
                    {
                        $resData['num']++;
                        if ($datum['create_time'] > $resData['time'])
                        {
                            $resData['time'] = $datum['create_time'];
                        }
                    } else
                    {
                        $resData['num'] = $resData['num'] + 10;
                    }
                }
            }
            catch (\Exception $e)
            {
                $resData = [
                    'num' => 0,
                    'time' => 0
                ];
            }
            return $resData;
        });
    }

    /**
     * 更新签到信息
     * @param int $uid
     * @param string $date
     * @param array $updateData
     * @throws \Exception
     */
    public function updateSignInData(int $uid, string $date, array $updateData)
    {
        CacheManage::getInstance()->setCacheConfig($this->signInCacheModel, $uid . ':' . $date)->setCache($updateData);

        CacheManage::getInstance()->setCacheConfig('lucky_planet.task_record', $uid . ':upgrade:1')->setCache([$date => $date]);
    }

    /**
     * 获取明日幸运星 过期数量 当幸运星被使用时【抽奖｜兑换】 删除改缓存
     * @param int $uid
     * @return int
     * @throws \Exception
     */
    public function getExpireLuckyNumByTomorrow(int $uid): int
    {
        $date = date('Ymd');
        $resData = CacheManage::getInstance()->setCacheConfig($this->cacheModel)->setCacheKeyDetail('tomorrow_expire', $uid . ':' . $date)
            ->setCacheTime(86400)
            ->setCacheType('string')
            ->getDataAndSet(function () use ($uid, $date)
            {
                // 明天过期 幸运星失效时间=（大于等于今天零点时间戳 小于明日零点时间戳）
                // 失效的时候计算当天失效的幸运星数量    大于等于昨日零点时间戳 小于今日零点时间戳
                $time = strtotime($date);  // 当天零点时间戳
                $tomorrowTime = $time + 86400;  // 明天零点时间
                try
                {
                    $data = $this->query("SELECT sum(`change_num` - `use_num`) as num FROM  `wechat_backup_07_18_14_43_00`.`app_user_lucky_change_record` WHERE `uid` = {$uid} AND `type` in (1,5) AND `expire_time` >= {$time} AND `expire_time` < {$tomorrowTime} AND `change_num` > `use_num` AND `lucky_status` = 1");

                    return json_encode($data['0']);
                }
                catch (\Exception $e)
                {
                    return `{"num":0}`;
                }
            }, [], 'tomorrow_expire');

        $resData = json_decode($resData, true);

        $num = $resData['num'] ?? 0;

        return (int)$num;
    }

    /**
     * @param array $data
     * @return bool
     */
    public function SaveData(array $data)
    {
        try
        {
            $id = $this->insertGetId($data);

            switch ($data['type'])
            {
                case 1:
                case 5:
                    $type = 1;
                    break;
                case 2:
                case 3:
                    $type = 2;
                    break;
                case 4:
                    $type = 3;
                    break;
            }


            $this->listDataAdd($data['uid'], [$id => $id], 0);
            if (isset($type))
            {
                $this->listDataAdd($data['uid'], [$id => $id], $type);
            }
        }
        catch (\Exception $e)
        {
            Log::write('幸运星变更记录 AppUserLuckyChangeRecord()->SaveData 异常：' . $e->getMessage() . '失败行数：' . $e->getLine(), 'error');
            return 0;
        }
        return $id;
    }

    /**
     * 更新
     * @param int $id
     * @param array $data
     * @return bool
     */
    public function UpdateData(int $id, array $data)
    {
        try
        {
            $this->where('id', $id)->update($data);

            CacheManage::getInstance()->setCacheConfig($this->cacheModel, $id)->setCache($data);
        }
        catch (\Exception $e)
        {
            Log::write('幸运星变更记录更新 AppUserLuckyChangeRecord()->UpdateData 异常：' . $e->getMessage() . '失败行数：' . $e->getLine(), 'error');
            return false;
        }
        return true;
    }

    /**
     * 重写数据时获取数据
     * @param $ids
     * @param $type
     * @param $sortType
     * @return array|false|string
     * @throws ApiException
     */
    public function getInfoByIdsInData($ids, $type, $sortType)
    {
        try
        {
            $where = [];
            if ($ids)
            {
                $where = ['id' => ['in', $ids]];
            } else
            {   // 0 全部 1 领取  2=>使用 3=>过期
                switch ($type[1])
                {
                    case 1:
                        $where['type'] = ['in', [1, 5]];
                        break;
                    case 2:
                        $where['type'] = ['in', [2, 3]];
                        break;
                    case 3:
                        $where['type'] = 4;
                        break;
                }
                $where['uid'] = $type[0];
            }

            return $this->where($where)->order('id ' . $sortType)->column('uid,status,type,change_num,changeed_num,use_num,task_id,draw_id,exchange_id,expire_time,extend,create_time', 'id');
        }
        catch (\Exception $e)
        {
            return [];
        }
    }

    /**
     * @param $cids
     * @param array $field
     * @return array
     * @throws \Exception
     */
    public function batchGetInfoByIds($cids, $field = [])
    {
        $datas = parent::batchGetInfoByIds($cids, $field);

        foreach ($datas as $id => $dataItem)
        {
            $datas[$id] = arrayKeyData2int($dataItem, ['id', 'status', 'uid', 'type', 'change_num', 'changeed_num', 'use_num', 'draw_id', 'task_id', 'exchange_id', 'expire_time', 'create_time']);
        }

        return $datas;
    }

    /**
     * 使用 幸运星 抽奖
     * @param array $luckyInfo
     * @param array $drawInfo
     * @return bool
     */
    public function luckyDrawSave(array $luckyInfo, array $drawInfo)
    {
        try
        {
            $num = 10;  // 抽奖消耗 幸运星数
            $nowTime = time();
            // 扣除幸运星
            $updateD = [
                'lucky_num' => $luckyInfo['lucky_num'] - $num,
                'use_lucky_num' => $luckyInfo['use_lucky_num'] + $num,
                'update_time' => $nowTime
            ];

            (new AppUserLuckyInfo())->UpdateData($luckyInfo['id'], $luckyInfo['uid'], $updateD);

            // 更新幸运星使用
            $recordDatas = Db::table('wechat_backup_07_18_14_43_00.app_user_lucky_change_record')->where(['uid' => $luckyInfo['uid'], 'type' => ['in', [1, 5]], 'lucky_status' => 1])
                ->where('`change_num` > `use_num`')->order('id asc')->field('id,change_num,use_num')->limit(10)->select();
            $num1 = 0;  // 当前使用数量
            foreach ($recordDatas as $recordDataItem)
            {
                $um = $recordDataItem['change_num'] - $recordDataItem['use_num'];   // 当前记录可使用数量
                $n = $num - $num1;
                $useNum = $n > $um ? $um : $n;
                Db::table('wechat_backup_07_18_14_43_00.app_user_lucky_change_record')->where('id', $recordDataItem['id'])->update(['use_num' => $recordDataItem['use_num'] + $useNum, 'update_time' => $nowTime]);
                $num1 += $useNum;
                if ($num === $num1)
                {
                    break;
                }
            }
            // 删除明日幸运星过期 数量缓存
            $date = date('Ymd');
            CacheManage::getInstance()->setCacheConfig($this->cacheModel)->setCacheKeyDetail('tomorrow_expire', $luckyInfo['uid'] . ':' . $date)->rmCache('tomorrow_expire');

            $expireTime = 0;
            if (in_array($drawInfo['type'], [1, 4, 5], true))
            {
                if ($drawInfo['type'] === 5)
                {
                    $day = $this->luckyExpireDay;
                } else
                {
                    $day = $drawInfo['days'] <= 0 ? 30 : $drawInfo['days'];
                }
                $expireTime = $nowTime + 86400 * $day;
            }
            // 写入 抽奖记录
            $insertData = [
                'status' => 0,
                'uid' => $luckyInfo['uid'],
                'type' => 3,
                'change_num' => $num,
                'changeed_num' => $updateD['lucky_num'],
                'use_num' => 0,
                'draw_id' => $drawInfo['id'],
                'exchange_id' => $drawInfo['type'] === 4 ? $drawInfo['data_id'] : 0,
                'expire_time' => $expireTime,
                'extend' => '',
                'create_time' => $nowTime,
            ];

            $adornId = $this->SaveData($insertData);

            // 发放奖品
            switch ($drawInfo['type'])
            {
                case 1: // 卡券
                    // 给 用户 发放卡券
                    $cid = $drawInfo['data_id'];
                    $userCouponModel = new UserCoupon();
                    $couponInfo = (new ZlCouponAttr())->getInfoById($cid, ['desc', 'type', 'rand_min', 'rand_max', 'ur_id', 'gids']);
                    $cData = [
                        'uid' => $luckyInfo['uid'],
                        'c_id' => $cid,
                        'ur_id' => $couponInfo['ur_id'],
                        'start_time' => $nowTime,
                        'end_time' => $expireTime,
                        'give_time' => $nowTime,
                        'status' => 0,
                        'price' => $couponInfo['type'] == 4 ? mt_rand($couponInfo['rand_min'], $couponInfo['rand_max']) : 0,
                        'is_give' => 0,
                        'create_time' => $nowTime,
                        'update_time' => 0,
                    ];
                    $ucId = $userCouponModel->insertGetId($cData);
                    $ids[$ucId] = $ucId; // 添加未用于ID
                    // 神策打点
                    $gidsArr = explode(',', $couponInfo['gids']);
                    $couponRangeArr = (new Goods())->where('id', 'in', $gidsArr)->column('name');
                    // 神策打点 75 获得优惠券 AcquireCoupon
                    SensorsData::track($luckyInfo['uid'], true, 'AcquireCoupon', [
                        'refer_name' => '',
                        'refer_link' => '',
                        'coupon_name' => $couponInfo['desc'],
                        'coupon_expire' => date('Y-m-d H:i:s', $cData['end_time']),
                        'coupon_type' => $userCouponModel->couponTypeName[$couponInfo['type']],
                        'coupon_range' => $couponRangeArr,
                        'acquire_channel' => '幸运星抽奖',
                        'is_give' => false,
                        'acquire_scene' => '抽奖',
                    ]);
                    // 未使用
                    $userCouponModel->listDataAdd($luckyInfo['uid'], $ids, 1);
                    break;
                case 2: // 准币
                    // 中奖概率为 0 先忽略
                    break;
                case 4: //兑换物
                    (new AppUserAdornInfo())->userAdornAdd($luckyInfo['uid'], $adornId);
                    break;
                case 5: // 幸运星
                    // 写入 幸运星中抽奖记录
                    $insertData = [
                        'status' => 0,
                        'uid' => $luckyInfo['uid'],
                        'type' => 5,
                        'change_num' => $drawInfo['num'],
                        'changeed_num' => $updateD['lucky_num'] + $drawInfo['num'],
                        'use_num' => 0,
                        'draw_id' => $drawInfo['id'],
                        'exchange_id' => 0,
                        'expire_time' => $expireTime,
                        'extend' => '',
                        'create_time' => $nowTime,
                    ];
                    $this->SaveData($insertData);
                    // 增加
                    $updateD2 = [
                        'lucky_num' => $updateD['lucky_num'] + $drawInfo['num'],
                        'total_lucky_num' => $luckyInfo['total_lucky_num'] + $drawInfo['num'],
                    ];
                    // 增加 幸运星
                    (new AppUserLuckyInfo())->UpdateData($luckyInfo['id'], $luckyInfo['uid'], $updateD2);
                    break;
                default:
                    // 下次再来 ｜ 实物 | 兑换物
            }
        }
        catch (\Exception $e)
        {
            Log::write("幸运星抽奖结果更新异常  AppUserLuckyChangeRecord=>luckyDrawSave();{$e->getMessage()};FIEL:{$e->getFile()};LINE:{$e->getLine()};");
            return false;
        }

        return true;
    }

    /**
     * 幸运星兑换
     * @param array $luckyInfo
     * @param array $adornInfo
     * @return bool
     */
    public function luckyExchangeAdorn(array $luckyInfo, array $adornInfo)
    {
        try
        {
            $nowTime = time();
            $num = $adornInfo['lucky_num'];
            // 扣除幸运星
            $updateD = [
                'lucky_num' => $luckyInfo['lucky_num'] - $num,
                'use_lucky_num' => $luckyInfo['use_lucky_num'] + $num,
                'update_time' => $nowTime
            ];

            (new AppUserLuckyInfo())->UpdateData($luckyInfo['id'], $luckyInfo['uid'], $updateD);

            // 更新幸运星使用
            $recordDatas = Db::table('wechat_backup_07_18_14_43_00.app_user_lucky_change_record')->where(['uid' => $luckyInfo['uid'], 'type' => ['in', [1, 5]], 'lucky_status' => 1])
                ->where('`change_num` > `use_num`')->order('id asc')->field('id,change_num,use_num')->limit($num)->select();
            $num1 = 0;  // 当前使用数量
            foreach ($recordDatas as $recordDataItem)
            {
                $um = $recordDataItem['change_num'] - $recordDataItem['use_num'];   // 当前记录可使用数量
                $n = $num - $num1;
                $useNum = $n > $um ? $um : $n;
                Db::table('wechat_backup_07_18_14_43_00.app_user_lucky_change_record')->where('id', $recordDataItem['id'])->update(['use_num' => $recordDataItem['use_num'] + $useNum, 'update_time' => $nowTime]);
                $num1 += $useNum;
                if ($num === $num1)
                {
                    break;
                }
            }

            // 删除明日幸运星过期 数量缓存
            $date = date('Ymd');
            CacheManage::getInstance()->setCacheConfig($this->cacheModel)->setCacheKeyDetail('tomorrow_expire', $luckyInfo['uid'] . ':' . $date)->rmCache('tomorrow_expire');

            // 写入 抽奖记录
            $insertData = [
                'status' => 0,
                'uid' => $luckyInfo['uid'],
                'type' => 2,    // 兑换
                'change_num' => $num,
                'changeed_num' => $updateD['lucky_num'],
                'use_num' => 0,
                'draw_id' => 0,
                'exchange_id' => $adornInfo['id'],
                'expire_time' => $nowTime + 86400 * $adornInfo['days'],
                'extend' => '',
                'create_time' => $nowTime,
            ];

            $adornId = $this->SaveData($insertData);

            (new AppUserAdornInfo())->userAdornAdd($luckyInfo['uid'], $adornId);

            $exchangeType = [
                1 => '头像框',
                2 => '徽章',
                3 => '动态标签',
            ];
            // 神策打点 202 幸运星兑换 LuckyStarExchange
            SensorsData::track($luckyInfo['uid'], true, 'LuckyStarExchange', [
                'exchange_num' => $num,   // 消耗幸运星数量
                'exchange_type' => $exchangeType[$adornInfo['type']],      //兑换类型  徽章|头像框|动态标签
                'adorn_name' => $adornInfo['name'] . $adornInfo['days'] . '天',    // "名称+天数  例如：忠实小行星徽章30天"
                'star_left' => $updateD['lucky_num'], // 兑换后剩余的余额
            ]);
        }
        catch (\Exception $e)
        {
            Log::write("幸运星兑换装扮更新异常  AppUserLuckyChangeRecord=>luckyExchangeAdorn();{$e->getMessage()};FIEL:{$e->getFile()};LINE:{$e->getLine()};");
            return false;
        }

        return true;
    }

    /**
     * 幸运星 变更记录
     * @param int $uid
     * @param int $dataType
     * @return array|mixed
     * @throws \Exception
     */
    public function LuckyNumChangeRecord(int $uid, int $dataType)
    {
        $data = $this->getListPage($uid, 'id', [], $dataType);

        $appLuckyExchangeModel = new AppLuckyExchange();
        $LuckyDrawModel = new AppLuckyDraw();
        $luckyTaskConfig = config('lucky_task');
        $res = [];
        $exchangeDatas = [];
        $drawDatas = [];
        foreach ($data['data'] as $datum)
        {
            $datum = arrayKeyData2int($datum, ['id', 'status', 'uid', 'type', 'change_num', 'changeed_num', 'use_num', 'draw_id', 'task_id', 'exchange_id', 'expire_time', 'create_time']);

            $type = 0;
            $title = '';
            $tip = '';
            $time = '';
            $btnText = '';
            $name = '';
            $tel = '';
            $address = '';
            $kd_num = '';
            $target = 'local';
            $link = 'empty';
            switch ($datum['type'])
            {
                case 1: // 领取
                    $time = date('Y.m.d H.i', $datum['create_time']);
                    $title = $luckyTaskConfig['task_list'][$datum['task_id']]['name'];
                    break;
                case 2: // 兑换
                    $time = date('Y.m.d H.i', $datum['create_time']);
                    if (!isset($exchangeDatas[$datum['exchange_id']]))
                    {
                        $exchangeDatas[$datum['exchange_id']] = $appLuckyExchangeModel->getInfoById($datum['exchange_id'], ['name', 'days']);
                    }
                    $title = $exchangeDatas[$datum['exchange_id']]['name'] . $exchangeDatas[$datum['exchange_id']]['days'] . '天';
                    $tip = '兑换';
                    break;
                case 3: // 抽奖
                    $time = date('Y.m.d H.i', $datum['create_time']);
                    $tip = '参与抽奖';
                    if (!isset($drawDatas[$datum['draw_id']]))
                    {
                        $drawDatas[$datum['draw_id']] = $LuckyDrawModel->getInfoById($datum['draw_id']);
                    }
                    $title = $drawDatas[$datum['draw_id']]['name'];
                    if ($drawDatas[$datum['draw_id']]['type'] === 1)
                    {
                        $type = 1;
                        $btnText = '卡券中心';
                    }

                    if ($drawDatas[$datum['draw_id']]['type'] === 3)
                    {
                        if ($datum['status'] === 1)
                        {
                            $type = 3;  // 实物中奖后未选择地址的样式
                            $btnText = '更换';
                            $extend = json_decode($datum['extend'], true);
                            $addData = $extend['mall'];
                            $name = $addData['name'];
                            $tel = $addData['phone'];
                            $address = str_replace('，', '', $addData['address']);
                        } elseif ($datum['status'] === 2)
                        {
                            $type = 4;  // 实物中奖后未选择地址的样式
                            $btnText = '已发货';
                            $extend = json_decode($datum['extend'], true);
                            $addData = $extend['mall'];
                            $name = $addData['name'];
                            $tel = $addData['phone'];
                            $address = str_replace('，', '', $addData['address']);
                            $kd_num = $addData['kd_id'];
                            $target = 'local';
                            $link = "mall_store_kd_detail?lpid={$datum['id']}&need_auth=2";
                        } else
                        {   // status = 0
                            $type = 2;  // 实物中奖后未选择地址的样式
                            $btnText = '选择收货地址';
                        }
                    }
                    break;
                case 4: // 过期销毁
                    $time = date('Y.m.d', $datum['create_time']);
                    $title = '过期销毁';
                    break;
                case 5: // 中奖获取
                    $time = date('Y.m.d H.i', $datum['create_time']);
                    $title = '抽奖获得';
                    break;
                default:
            }

            $res[] = [
                'id' => $datum['id'],
                'title' => $title,
                'num' => in_array($datum['type'], [1, 5], true) ? '+' . $datum['change_num'] : '-' . $datum['change_num'], // 变化的数量
                'time' => $time, //  过期销毁的时间只精确到天
                'tip' => $tip, // 参与抽奖、兑换
                'type' => $type, // 0=>不带按钮,1=>卡券中奖的样式,2=>实物中奖后未选择地址的样式,3=>实物中奖后已选择地址的样式,4=>实物中奖后已发货的样式
                'btn_text' => $btnText, // 卡券中心>(type=1)、选择收货地址>(type=2)、更换(type=3)、已发货（type=4）
                'name' => $name, // 收货人名 (type=3|type=4)
                'tel' => $tel, // 收货人手机号 (type=3|type=4)
                'address' => $address, // 收货地址 (type=3|type=4)
                'kd_num' => $kd_num, // 运单号（后面要带复制按钮）(type=4)
                'target' => $target, //
                'link' => $link, // 跳转到物流详情页面
            ];
        }

        $data['data'] = $res;

        return $data;
    }
}
